#!/bin/bash
# OpenBMC编译脚本
# 功能：初始化Yocto环境并编译核心共享库
# 使用方法：在Docker容器内运行此脚本

set -e  # 遇到错误立即退出
set -u  # 使用未定义变量时报错

# ============================================================================
# 配置区域
# ============================================================================

# OpenBMC源码目录
OPENBMC_SOURCE="${OPENBMC_SOURCE:-/workspace/data/openbmc_source}"
# 构建输出目录
BUILD_OUTPUT="${BUILD_OUTPUT:-/workspace/data/build}"
# 目标机器平台
MACHINE="${MACHINE:-qemuarm}"
# 并行编译线程数（根据CPU核心数调整）
BB_NUMBER_THREADS="${BB_NUMBER_THREADS:-$(nproc)}"
PARALLEL_MAKE="${PARALLEL_MAKE:-$(nproc)}"

# 需要编译的核心库列表
CORE_LIBRARIES=(
    "sdbusplus"
    "libpldm"
    "phosphor-logging"
    "phosphor-dbus-interfaces"
    "gpioplus"
    "stdplus"
)

# ============================================================================
# 函数定义
# ============================================================================

# 日志函数
log_info() {
    echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $*"
}

log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $*" >&2
}

log_success() {
    echo "[SUCCESS] $(date '+%Y-%m-%d %H:%M:%S') - $*"
}

# 检查目录是否存在
check_directory() {
    local dir="$1"
    if [ ! -d "$dir" ]; then
        log_error "目录不存在: $dir"
        return 1
    fi
    return 0
}

# 初始化Yocto构建环境
init_yocto_env() {
    log_info "初始化Yocto构建环境..."
    
    cd "$OPENBMC_SOURCE" || {
        log_error "无法进入OpenBMC源码目录: $OPENBMC_SOURCE"
        exit 1
    }
    
    # 检查setup脚本是否存在
    if [ ! -f "setup" ]; then
        log_error "找不到setup脚本，请确认OpenBMC源码已正确克隆"
        exit 1
    fi
    
    # 运行setup脚本初始化环境
    log_info "运行 '. setup $MACHINE' 初始化构建环境..."
    # 注意：这里需要source setup脚本以设置环境变量
    . setup "$MACHINE"
    
    log_success "Yocto环境初始化完成"
}

# 配置local.conf
configure_local_conf() {
    log_info "配置local.conf..."
    
    local conf_file="$OPENBMC_SOURCE/build/conf/local.conf"
    
    if [ ! -f "$conf_file" ]; then
        log_error "local.conf文件不存在: $conf_file"
        exit 1
    fi
    
    # 备份原始配置
    cp "$conf_file" "$conf_file.backup"
    
    # 追加优化配置
    cat >> "$conf_file" << EOF

# ============================================================================
# OpenBMC ABI分析工具 - 自定义配置
# ============================================================================

# 设置目标机器
MACHINE = "$MACHINE"

# 并行编译优化
BB_NUMBER_THREADS = "$BB_NUMBER_THREADS"
PARALLEL_MAKE = "-j $PARALLEL_MAKE"

# 启用调试符号（用于ABI分析）
EXTRA_IMAGE_FEATURES += "dbg-pkgs"
DEBUG_BUILD = "1"

# 启用共享状态缓存（加速后续编译）
SSTATE_DIR = "\${TOPDIR}/sstate-cache"

# 减少不必要的包以加快编译
DISTRO_FEATURES_remove = "x11 wayland"

# 保留源码和构建目录（便于分析）
INHERIT += "rm_work_and_downloads"
RM_WORK_EXCLUDE += "sdbusplus libpldm phosphor-logging phosphor-dbus-interfaces"

# 日志配置
BBINCLUDELOGS = "yes"
EOF
    
    log_success "local.conf配置完成"
}

# 编译单个库
build_library() {
    local lib_name="$1"
    log_info "开始编译库: $lib_name"
    
    cd "$OPENBMC_SOURCE/build" || exit 1
    
    # 使用bitbake编译
    if bitbake "$lib_name" 2>&1 | tee "$BUILD_OUTPUT/build_${lib_name}.log"; then
        log_success "库编译成功: $lib_name"
        return 0
    else
        log_error "库编译失败: $lib_name"
        log_error "详细日志请查看: $BUILD_OUTPUT/build_${lib_name}.log"
        return 1
    fi
}

# 编译所有核心库
build_all_libraries() {
    log_info "开始编译 ${#CORE_LIBRARIES[@]} 个核心库..."
    
    local success_count=0
    local fail_count=0
    local failed_libs=()
    
    for lib in "${CORE_LIBRARIES[@]}"; do
        if build_library "$lib"; then
            ((success_count++))
        else
            ((fail_count++))
            failed_libs+=("$lib")
        fi
    done
    
    # 输出编译摘要
    echo ""
    log_info "========================================"
    log_info "编译摘要"
    log_info "========================================"
    log_info "总计: ${#CORE_LIBRARIES[@]} 个库"
    log_success "成功: $success_count 个"
    
    if [ $fail_count -gt 0 ]; then
        log_error "失败: $fail_count 个"
        log_error "失败的库: ${failed_libs[*]}"
        return 1
    fi
    
    log_success "所有库编译完成！"
    return 0
}

# ============================================================================
# 主流程
# ============================================================================

main() {
    log_info "========================================"
    log_info "OpenBMC核心库编译脚本"
    log_info "========================================"
    log_info "源码目录: $OPENBMC_SOURCE"
    log_info "输出目录: $BUILD_OUTPUT"
    log_info "目标平台: $MACHINE"
    log_info "并行线程: $BB_NUMBER_THREADS"
    log_info "========================================"
    
    # 检查必要目录
    check_directory "$OPENBMC_SOURCE" || exit 1
    check_directory "$BUILD_OUTPUT" || exit 1
    
    # 初始化Yocto环境
    init_yocto_env
    
    # 配置local.conf
    configure_local_conf
    
    # 编译所有核心库
    if build_all_libraries; then
        log_success "========================================"
        log_success "编译任务全部完成！"
        log_success "========================================"
        exit 0
    else
        log_error "========================================"
        log_error "部分库编译失败"
        log_error "========================================"
        exit 1
    fi
}

# 执行主流程
main "$@"

